package com.cy.demo1.algorithm;

import com.cy.demo1.entity.Result2;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;

//public class App extends JPanel{
public class App{
    public double b = 0;//TPR
    public double c = 0;//FPR
    public double a = 0;
    public double d = 0;
    public double e = 0;
    public int size1 ;

    public float acc;
    public float pre;
    public float rec;
    public float ff1;
    public float auc;

    public String rocx;

    public String rocy;
    public double f[][] = new double[11][2];
    public double g[] = new double[11];
    public double h[] = new double[11];
    public double[][] gradient_function(int size, double[][] theta, double[][] x, double [][] y){
        double m = 1.0/62.0;
        double [][]diff = new double[size][1];
        double [][]gradient = new double[62][1];
        for(int i =0;i<size;i++){
            for(int j =0;j<62;j++){
                diff[i][0] = diff[i][0] + x[i][j]*theta[j][0];
            }
            diff[i][0] = diff[i][0] - y[i][0];
            //System.out.println("awsl");
            //System.out.println(diff[i][0]);
        }
        double [][] x_zhuan = new double[62][size];
        for(int i = 0 ;i< 62; i++){
            for(int j = 0;j<size;j++){
                x_zhuan[i][j] = x[j][i];
            }
        }
        for(int i = 0;i<62;i++){
            for(int j = 0;j<size;j++){
                gradient[i][0] =  gradient[i][0] + x_zhuan[i][j]*diff[j][0];
            }
            gradient[i][0] = m*gradient[i][0];
        }

        return gradient;
    }
    public double[][] gradient_descent(int size,double[][] theta,double[][]x ,double [][] y){//批量梯度下降函数
        double [][]gradient = new double[62][1];
        double rate = 0.0005;
        int epoch = 100;
        gradient = gradient_function(size,theta,x, y);
        for(int i =0;i<62;i++){
            //System.out.println(gradient[i][0]);
        }
        
        for(int i = 0;i<epoch;i++){
            for(int j = 0;j<62;j++){
                theta[j][0] = theta[j][0] - rate *gradient[j][0];
            }
            gradient = gradient_function(size,theta,x, y);
        }
        return theta; 
    }
    public double[][] prediction(int size,double[][] x , double[][] theta){//预测函数
        double a[][] = new double[size][1];
        for(int i = 0; i<size; i++){
            for(int j =0;j<62;j++){
                a[i][0] = a[i][0] + x[i][j] * theta[j][0];
            }
            //System.out.println(a[i][0]);
        }
        return a;
    }
    public double[][] sigmoid(int size,double[][] a){//sigmoid函数
        double e = Math.E;
        for(int i =0; i<size;i++){
            a[i][0] = 1.0/(1.0+ Math.pow(e,-a[i][0]));
            if(a[i][0] == 1){
                a[i][0] = 0.9999999999999998;
            }
            //System.out.println(a[i][0]);
        }
        return a;
    }
    public double[][] Standardization(int size ,double[][] x){//标准化函数
        double average = 0;
        for(int i = 0;i<size;i++){
              average = average + x[i][0];
        }
        average = average/size;
        double average1 = 0; 
        for(int i = 0;i<size;i++){
          average1 = average1 + Math.pow(average-x[i][0], 2);
    }
          average1 = average1/size;
          average1 = Math.sqrt(average1);
          for(int i = 0;i<size;i++){
            x[i][0] = (x[i][0]- average)/average1;
          }
          return x;
    }
    public double[][] Standardization1(int size ,double[][] x){//标准化函数
        for(int j = 0;j<62;j++){
            double average = 0;
            for(int i = 0;i<size;i++){
                  average = average + x[i][j];
            }
            average = average/size;
            double average1 = 0; 
            for(int i = 0;i<size;i++){
              average1 = average1 + Math.pow(average-x[i][j], 2);
        }
              average1 = average1/size;
              average1 = Math.sqrt(average1);
              for(int i = 0;i<size;i++){
                x[i][j] = (x[i][j]- average)/average1;
              }
        }
          return x;
    }
    public double accuracy(int size,double[][] x, double[][] y){
        double a = 0;
        double b = 0;
        for(int i = 0;i<size;i++){
            //System.out.println("x="+x[i][0]);
            //System.out.println("y="+y[i][0]);
            if((x[i][0] == 0 && y[i][0] == 0)||(x[i][0] == 1 && y[i][0] == 1)){
                b++;
            }
        }
        a = b/size;
        return a;
    }
    public double precision(int size,double[][] x,double[][] y){
        double a = 0;
        double b =0;
        double c = 0;
        for(int i = 0;i<size;i++){
            if((x[i][0] == 0 && y[i][0] == 0)){
                b++;
            }
            if((x[i][0] == 0 && y[i][0] == 0)||(x[i][0] == 0 && y[i][0] == 1)){
                a++;
            }
        }
        return c= b/a;
    }
    public double recall(int size,double[][] x,double[][] y){
        double a = 0;
        double b =0;
        double c = 0;
        for(int i = 0;i<size;i++){
            if((x[i][0] == 0 && y[i][0] == 0)){
                b++;
            }
            if((x[i][0] == 0 && y[i][0] == 0)||(x[i][0] == 1 && y[i][0] == 0)){
                a++;
            }
        }
        return c= b/a;
    }
 /*   public void roc(){
        Graphics g  = getGraphics();
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        App a1 = new App();
        frame.add(a1);
        frame.setTitle("ROC曲线");
        frame.setVisible(true);
    }*/
    
    public void paintComponent(Graphics g){
        g.setColor(Color.black);
        g.drawLine(10, 10, 10, 450);
        g.drawLine(10, 450, 450, 450);
        for(int i = 0;i<10;i++){
            g.drawLine(10+(int)(f[i][0]*440), 10+(int)((1-f[i][1])*440), 10+(int)(f[i+1][0]*440), 10+(int)((1-f[i+1][1])*440));
        }
    }
    public void AUC(int size,double[][] x,double[][] y){
        double a1 = 0;
        for(int i = 0;i<size;i++){
            if(y[i][0] == 0){
                d++;
            }
            if(y[i][0] == 1){
                e++;
            }
        }
        //System.out.println("d:"+d);
        //System.out.println("e:"+e);
        for(int i = 0 ;i<=10 ;i++){
            for(int j = 0 ;j<size;j++){
                if((x[j][0] >= a)&&y[j][0] == 0){
                    b++;
                }
                if((x[j][0] >= a)&&y[j][0] == 1){
                    c++;
                }
            }
            //System.out.println("b:"+b);
            //System.out.println("c:"+c);
            //System.out.println("a:"+a);
            b = b/d;
            c = c/e;
            f[i][1] = c;
            f[i][0] = b;
            //System.out.println("TPR:"+b);
            //System.out.println("FPR:"+c);
            b = 0;
            c = 0;
            a = a+0.1;
        }
        for(int i = 0;i<10;i++){
            a1 =a1 + (f[i][1]+f[i+1][1])*(f[i][0]-f[i+1][0])/2;
        }
        System.out.println("AUC面积:"+a1);

        auc = (float) a1;
    }
    public void test(String filemane){
        File csv = new File(filemane);
          csv.setReadable(true);
          csv.setWritable(true);
          InputStreamReader isr = null;
          BufferedReader br = null;
          try {
          isr = new InputStreamReader(new FileInputStream(csv), "UTF-8");
           br = new BufferedReader(isr);
          } catch (Exception e) {
          e.printStackTrace();
          }
           String line = "";
          ArrayList<String> records = new ArrayList<>();
          try {
          while ((line = br.readLine()) != null) {
           //System.out.println(line);
           records.add(line);
           }
           System.out.println("csv表格读取行数：" + records.size());
           } catch (IOException e) {
           e.printStackTrace();
           }
           double a = (records.size()-1)*0.7;
           int b = (int) a;
           int c = records.size() - b - 1;
           double[][] x_train = new double[b][62];//训练集
           double[][] x_test = new double[c][62];//测试集
           double[][] y_train = new double[b][1]; 
           double[][] y_test = new double[c][1];
           System.out.println("测试集数量："+c);
           //将csv文件数据存入矩阵
           String []d = (String[])records.toArray(new String[records.size()]);
           for(int i = 0;i<b;i++){//填充训练集
              String[] s3 = d[i+1].split(",");
              for(int j = 0;j<61;j++){
                  double g = Double.parseDouble(s3[j]);
                  x_train[i][j] = g;
              }
              String aw = new String("clean");
              String aw1 = new String("buggy");
              if(s3[61].equals(aw)){
                  y_train[i][0] = 0;
              }
              if(s3[61].equals(aw1)){
                  y_train[i][0] = 1;
              }
          }
          for(int i = 0;i<c;i++){//填充测试集
              String[] s3 = d[b+i+1].split(",");
              for(int j = 0;j<61;j++){
                  double g = Double.parseDouble(s3[j]);
                  x_test[i][j] = g;
              }
              String aw = new String("clean");
              String aw1 = new String("buggy");
              if(s3[61].equals(aw)){
                  y_test[i][0] = 0;
              }
              if(s3[61].equals(aw1)){
                  y_test[i][0] = 1;
              }
          }
          //添加偏置
          for(int i = 0 ;i< b;i++){
              x_train[i][61] = 1;
          }
          for(int i = 0 ;i< c;i++){
            x_test[i][61] = 1;
        }
            //数据标准化
        x_train =Standardization1(b, x_train);
        for(int i = 0;i<b;i++){
            for(int j = 0;j<62;j++){
                if(Double.isNaN(x_train[i][j])){
                    x_train[i][j] = 0;
                }
                //System.out.println(x_train[i][j]);
            }
        }
        //x_test = qys.Standardization1(c, x_test);
        y_train = Standardization(b, y_train);
        //y_test = qys.Standardization(c, y_test);
          //初始化参数矩阵
          double[][]theta = new double[62][1];
          for(int i =0 ;i<62;i++){
              //theta[i][0] = 0;
          }

          //测试
          theta = gradient_descent(b, theta, x_train, y_train);
          for(int i =0 ;i<62;i++){
            //System.out.println(theta[i][0]);
          }
          //System.out.println("awsl");
          double a1[][] = new double[c][1];
          a1 = prediction(c, x_test, theta);
          a1 = sigmoid(c,a1);
          //System.out.println("a1:" + a1);
          //System.out.println("y_test:" + y_test);
          AUC(c, a1, y_test);
          for(int i =0; i<c;i++){
            //System.out.println(a1[i][0]);
          }
          for(int i =0; i<c;i++){//判断
            if(a1[i][0] >=0.5){
                a1[i][0] = 0;
            }else{
                a1[i][0] = 1;
            }
        }
           for(int i =0 ;i<c;i++){
            //System.out.println(a1[i][0]);
          }
          double accuracy1;
          double accuracy2;
          double accuracy3;
          double f1;
          accuracy1 = accuracy(c, a1, y_test);
          accuracy2 = precision(c, a1, y_test);
          accuracy3 = recall(c, a1, y_test);
          f1 = 2*(accuracy2* accuracy3)/(accuracy2+accuracy3);
          System.out.println("正确率："+accuracy1);
          System.out.println("精确率："+accuracy2);
          System.out.println("召回率："+accuracy3);
          System.out.println("f1值："+f1);

          acc = (float)accuracy1;
          pre = (float)accuracy2;
          rec = (float)accuracy3;
          ff1 = (float)f1;

          //roc();
          for(int i = 0;i<10;i++){
            g[i] = f[i][0];
            System.out.println(g[i]);
            h[i] = f[i][1];
            System.out.println(h[i]);
         }

          rocx = String.valueOf(g[0]);
          rocy = String.valueOf(h[0]);
          for(int i = 1;i<10;i++){
              rocx = rocx + "," + String.valueOf(g[i]);
              rocy = rocy + "," + String.valueOf(h[i]);
          }

    }
    public double[] roc_value1(){//横坐标
        return g;
    }
    public double[] roc_value2(){//纵坐标
        return h;
    }
//    public static void main(String[] args) throws Exception {
//         App qys = new App();
//         qys.test("C:\\Users\\tanxy\\Desktop\\csv\\JDT.csv");
//    }
    public Result2 getResult2(String str){
        //App qys = new App();
        test(str);
        Result2 result2 = new Result2();
        result2.setAcc(acc);
        result2.setPre(pre);
        result2.setRec(rec);
        result2.setF1(ff1);
        result2.setAuc(auc);
        result2.rocx = rocx;
        result2.rocy = rocy;
//        result2.setRocx(rocx);
//        result2.setRocy(rocy);
//        System.out.println("rox: " + result2.getRocx());
//        System.out.println("roy: " + result2.getRocy());
//        System.out.println("rox: " + qys.rocx);
//        System.out.println("roy: " + qys.rocy);
        return result2;
    }
}
